﻿using ServiceMonitor.Core;
using ServiceMonitor.Model;
using ServiceMonitor.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ServiceMonitor.Services
{
    /// <summary>
    /// SpringBoot监控服务实现类
    /// </summary>
    public class SpringBootMonitorServiceImpl : AbstractStartMonitoringService
    {

        /// <summary>
        /// 当前运行的jar进程信息
        /// </summary>
        private JarProcessInfo processInfo;
        private readonly Action<String> _logger;
        private readonly MonitorConfig _config;
        private Timer _monitoringTimer;
        private static Object lock_obj = new Object();
        public SpringBootMonitorServiceImpl(
            EventHandler<ServiceStatusChangedEventArgs> eventHandler,
            MonitorConfig config,
            Action<String> logger) : base(eventHandler)
        {
            this._logger = logger;
            this._config = config;
        }
        public override void Start(Object obj)
        {
            _monitoringTimer = new Timer(CheckServiceStatus, null, Timeout.Infinite, Timeout.Infinite);
            _monitoringTimer.Change(0, _config.CheckInterval * 1000);
        }

        public override void Stop()
        {
            StopJar();
        }

        public class A
        {
            public A(bool isListening, string message)
            {
                this.IsListening = isListening;
                this.Message = message;
            }
            public bool IsListening { get; set; }
            public string Message { get; set; }
        }
        // 专用的端口监听检测方法
        private A CheckPortListening(int port)
        {
            if (port <= 0) return new A(false, "未配置有效端口");
            try
            {
                // 使用.NET内置类快速检查端口状态
                IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
                IPEndPoint[] listeners = ipGlobalProperties.GetActiveTcpListeners();

                bool isListening = listeners.Any(endPoint => endPoint.Port == port);
                return new A(isListening, isListening ? $"端口 {port} 正在监听" : $"端口 {port} 未监听");
            }
            catch (Exception ex)
            {
                return new A(false, $"端口检测错误: {ex.Message}");
            }
        }

        // 处理启动超时逻辑
        private void ProcessStartTimeout(MonitorConfig config, JarProcessInfo processInfo, bool isPortListening)
        {
            string statusMessage = "运行中 (>3分钟)";

            // 添加端口状态信息
            statusMessage += " - " + (isPortListening ? "端口已监听，健康检测未就绪" : "端口未监听");

            // 更新状态
            UpdateStatus(config.Id, statusMessage);

            // 如果端口没有监听，尝试重启应用
            if (!isPortListening)
            {
                AttemptRestartJar(config);
            }
        }

        private void AttemptRestartJar(MonitorConfig config)
        {
            try
            {
                _logger($"尝试重启服务 #{config.Id}: {config.Name}");
                StopJar();
                Thread.Sleep(2000); // 等待2秒
                StartJar();
            }
            catch (Exception ex)
            {
                UpdateStatus(config.Id, $"重启失败: {ex.Message}");
            }
        }

        private bool CheckJarHealthEndpoint(MonitorConfig config)
        {
            try
            {
                // 尝试可能的健康检查端点
                string[] endpoints = {
                    $"http://localhost:{config.Port}/actuator/health",
                    $"http://localhost:{config.Port}/health",
                    "http://localhost:8080/actuator/health",
                    "http://localhost:8080/health"
                };

                foreach (string url in endpoints)
                {
                    try
                    {
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                        request.Timeout = 2000; // 快速检查
                        request.Method = "GET";

                        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                        using (Stream stream = response.GetResponseStream())
                        {
                            if (stream != null)
                            {
                                using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                                {
                                    string jsonResponse = reader.ReadToEnd();

                                    // 简单判断健康状态
                                    if (jsonResponse.IndexOf("\"status\":\"UP\"", StringComparison.OrdinalIgnoreCase) >= 0 ||
                                        jsonResponse.IndexOf("UP", StringComparison.OrdinalIgnoreCase) >= 0)
                                    {
                                        return true;
                                    }

                                    if (jsonResponse.Length > 100)
                                    {
                                        jsonResponse = jsonResponse.Substring(0, 100) + "...";
                                    }
                                    _logger($"JAR #{config.Id}健康检查失败: {jsonResponse}");
                                }
                            }
                        }
                        return false;
                    }
                    catch (WebException)
                    {
                        // 尝试下一个端点
                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger($"JAR #{config.Id}健康检查失败: {ex.Message}");
            }

            return false;
        }

        public void StartJar()
        {
            if (!this._config.IsActive) return;
            if (this._config.Type != MonitorType.StringBoot) return;
            this.StopJar();
            try
            {
                var process = new Process();
                process.StartInfo.FileName = "java";
                process.StartInfo.Arguments = $"{this._config.JavaArgs} -jar \"{this._config.JarPath}\"";
                process.StartInfo.WorkingDirectory = string.IsNullOrWhiteSpace(this._config.WorkingDirectory)
                    ? Path.GetDirectoryName(this._config.JarPath)
                    : this._config.WorkingDirectory;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.CreateNoWindow = true;
                process.EnableRaisingEvents = true;
                process.Exited += (sender, e) =>
                {

                    processInfo?.Process.Dispose();
                    processInfo = null;
                    UpdateStatus(_config.Id, $"进程已退出");
                };

                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                processInfo = new JarProcessInfo
                {
                    Process = process,
                    StartTime = DateTime.UtcNow
                };
                UpdateStatus(_config.Id, "JAR进程已启动");
            }
            catch (Exception ex)
            {
                UpdateStatus(_config.Id, $"启动JAR失败: {ex.Message}");
            }
        }

        public void StopJar()
        {
            // 通过检测SpringBoot绑定的端口来停止JAR进程
            String kill = PortProcessTerminator.KillProcessByPort(_config.Port);
            _logger($"尝试通过端口 {_config.Port} 杀死JAR进程:执行结果 {kill}");
            try
            {
                if (processInfo == null) return;
                if (!processInfo.Process.HasExited)
                {
                    processInfo.Process.Kill();
                    processInfo.Process.WaitForExit(5000);
                }
                processInfo?.Process.Dispose();
            }
            catch (Exception ex)
            {
                _logger($"停止JAR #{this._config.Id} 失败: {ex.Message}");
            }
            base.UpdateStatus(this._config.Id, "JAR进程已停止");
        }

        public override void CheckServiceStatus(object state)
        {
            lock (lock_obj)
            {
                if (!MonitoringService.GetIsMonitoring())
                {
                    this.Stop();
                    return;
                }

                // 1. 首先检查进程是否存在
                if (this.processInfo == null)
                {
                    StartJar();
                    return;
                }
                // 2. 检查进程状态
                if (processInfo.Process.HasExited)
                {
                    UpdateStatus(_config.Id, $"进程已退出, 代码: {processInfo.Process.ExitCode}");
                    StartJar();
                    return;
                }
                // 3. 检查端口是否已被监听（关键改进）
                var portListeningStatus = CheckPortListening(_config.Port);
                bool isPortListening = portListeningStatus.IsListening;
                string portStatusMessage = portListeningStatus.Message;

                // 4. 检查启动超时
                if ((DateTime.UtcNow - processInfo.StartTime).TotalMinutes > 3)
                {
                    ProcessStartTimeout(_config, processInfo, isPortListening);
                    return;
                }
                // 5. 基于端口状态决定下一步操作
                if (!isPortListening)
                {
                    UpdateStatus(_config.Id, "启动中: 端口尚未监听");
                    return;
                }
                // 6. 执行健康检查
                bool isHealthy = CheckJarHealthEndpoint(_config);
                UpdateStatus(_config.Id, isHealthy ? "运行正常 (健康检查通过)" : "运行中 (健康端点无响应)");
            }
        }
    }
}
